#!/usr/bin/python3

import logging
from logging.handlers import RotatingFileHandler
import os
import gzip
import shutil

# 定义日志的格式
FORMAT = "%(asctime)s [%(levelname)s]: %(message)s"

class DuplicateFilter(logging.Filter):
    def __init__(self, threshold):
        super().__init__()
        self.last_logs = []
        self.repeat_count = {}
        self.threshold = threshold

    def filter(self, record):
        current_log = record.msg.split(",")[0]
        if current_log not in self.last_logs:
            self.last_logs.append(current_log)
            self.repeat_count[current_log] = 1
            if len(self.last_logs) > 5:
                oldest_log = self.last_logs.pop(0)
                del self.repeat_count[oldest_log]
        else:
            self.repeat_count[current_log] += 1

        return self.repeat_count[current_log] <= self.threshold

class CompressingRotatingFileHandler(RotatingFileHandler):
    """
    自定义的 RotatingFileHandler，增加日志压缩功能，并检测 .gz 文件
    """
    # 覆盖父类的 doRollover 方法，按照压缩文件的逻辑轮换日志
    def doRollover(self):
        
        if self.stream:
            self.stream.close()
            self.stream = None

        # 轮换和压缩日志文件时，检测压缩后的文件名
        for i in range(self.backupCount - 1, 0, -1):
            sfn = f"{self.baseFilename}.{i}.gz"
            dfn = f"{self.baseFilename}.{i + 1}.gz"
            if os.path.exists(sfn):
                if os.path.exists(dfn):
                    os.remove(dfn)
                os.rename(sfn, dfn)

        # 压缩当前日志文件
        dfn = f"{self.baseFilename}.1.gz"
        if os.path.exists(dfn):
            os.remove(dfn)
        self.compress_log(self.baseFilename, dfn)

        # 重新打开新的日志文件进行写入
        if not self.delay:
            self.stream = self._open()

    def compress_log(self, log_filename, gz_filename):
        """
        压缩日志文件为 .gz 格式
        """
        with open(log_filename, 'rb') as f_in:
            with gzip.open(gz_filename, 'wb') as f_out:
                shutil.copyfileobj(f_in, f_out)
        os.remove(log_filename)

class RMLog():
    def __init__(self) -> None:
        loglevel = logging.DEBUG
        logFileName = "/test666/test.log"
        logging.basicConfig(format=FORMAT, level=loglevel, datefmt='%m-%d,%H:%M:%S',
                            handlers=[CompressingRotatingFileHandler(logFileName, maxBytes=1 * 1024, backupCount=5)])
        logging.getLogger().addFilter(DuplicateFilter(threshold=20))
        logging.info("RMLog init file[%s]", logFileName)


def main():
    RMLog()
    count = 0
    logging.critical('[TEST2]: begin record')
    while count < 60:
        logging.info('[TEST2]: this logging is a test info [%s]', count)
        logging.info('[TEST2]: this logging is a test1 info too, but it not a repeat info')
        logging.info('[TEST2]: this logging is a test2 info too, but it not a repeat info')
        logging.info('[TEST2]: this logging is a test3 info too, but it not a repeat info')
        logging.info('[TEST2]: this logging is a test4 info too, but it not a repeat info')
        count += 1

if __name__ == "__main__":
    main()


